package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Blog;
import com.hmdp.entity.Follow;
import com.hmdp.entity.User;
import com.hmdp.mapper.FollowMapper;
import com.hmdp.service.IFollowService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IUserService;
import com.hmdp.utils.UserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements IFollowService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IUserService userService;

    @Override
    public Result checkFollow(Long id) {
        LambdaQueryWrapper<Follow> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(id != null, Follow::getFollowUserId, id);
        if (UserHolder.getUser() == null) {
            return Result.fail("请先完成登录！");
        }
        wrapper.eq(Follow::getUserId, UserHolder.getUser().getId());
        Follow one = getOne(wrapper);
        if (one == null) {
            return Result.ok(false);
        }
        return Result.ok(true);
    }

    @Override
    public Result followOrNot(Long id, boolean isFollow) {
        /*Result result = this.checkFollow(id);
        boolean resultData = (boolean) result.getData();*/
        if (isFollow == false) {
            //已经关注过了，再次点击则取消关注
            LambdaQueryWrapper<Follow> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Follow::getFollowUserId, id);
            Long id1 = UserHolder.getUser().getId();
            if (id1 == null) {
                return Result.fail("请先完成登录！");
            }
            wrapper.eq(Follow::getUserId, id1);
            boolean remove = remove(wrapper);
            if (remove != true) {
                return Result.fail("取消关注失败！");
            }
            //因为以后关注了会存入redis中，所以这里要操作一下
            stringRedisTemplate.opsForSet().remove("Follow:" + String.valueOf(id1), String.valueOf(id));
            return Result.ok(remove);
        }
        //没有关注过，点击则实现关注
        Follow follow = new Follow();
        Long id1 = UserHolder.getUser().getId();
        if (id1 == null) {
            return Result.fail("请先登录！");
        }
        follow.setFollowUserId(id);
        follow.setUserId(id1);
        boolean save = save(follow);
        //因为关注要结合redis，所以这里要对redis操作一下
        stringRedisTemplate.opsForSet().add("Follow:" + String.valueOf(id1), String.valueOf(id));
        return Result.ok(save);
    }

    @Override
    public Result commonFollow(Long id) {
        /*实现共同关注功能，其实就是查出当前用户关注了谁（集合），然后就是我们查看的用户关注了谁（集合）
         * 这两个集合求一个交集即可------>因为我们在学redis，在redis中的set其实可以用指令求交集，所以我们用用
         * redis来实现我们的业务功能
         * */
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            return Result.fail("请先完成登录！");
        }
        Long userId = user.getId();
       /* //查询我们当前用户关注了谁并存入redis中
        queryAndSaveToRedis(userId);
        //查询我们查看的用户关注了谁并存入redis中
        queryAndSaveToRedis(id);*/
        //比较两个set集合，求出它们的交集
        List<UserDTO> userDTOS = commonFollowFuntion(id, userId);
        return Result.ok(userDTOS);
    }

    /*下面这个方法多余写了，害*/
    @Transactional
    public List<UserDTO> queryAndSaveToRedis(Long userId) {
        LambdaQueryWrapper<Follow> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Follow::getUserId, userId);
        List<Follow> follows = list(wrapper);

        List<UserDTO> userDTOS = follows.stream().map(item -> {
            Long followUserId = item.getFollowUserId();
            User byId = userService.getById(followUserId);
            UserDTO userDTO = BeanUtil.copyProperties(byId, UserDTO.class);
            //把关注的用户的id存入redis中
            stringRedisTemplate.opsForSet().add("Follow:" + String.valueOf(userId), String.valueOf(userDTO.getId()));
            return userDTO;
        }).collect(Collectors.toList());
        return userDTOS;
    }

    private List<UserDTO> commonFollowFuntion(Long id1, Long id2) {
        //求交集，在redis中的指令为 sinter key1 key2 ,在redisTemplate封装的方法为intersect()
        Set<String> commonFollowList = stringRedisTemplate.opsForSet()
                .intersect("Follow:" + id1.toString(), "Follow:" + id2.toString());
        List<UserDTO> userDTOS = commonFollowList.stream().map(item -> {
            Long userId = Long.valueOf(item);
            User byId = userService.getById(userId);
            UserDTO userDTO = BeanUtil.copyProperties(byId, UserDTO.class);
            return userDTO;
        }).collect(Collectors.toList());

        return userDTOS;
    }


}
